package auto.app.service.impl;

import auto.app.controller.from.Scheduled.ScheduledAdd;
import auto.app.controller.from.Scheduled.ScheduledPage;
import auto.app.controller.from.Scheduled.ScheduledUpdate;
import auto.app.controller.info.ScheduledInfo.ScheduledPageInfo;
import auto.app.enums.JobExecutorHandler;
import auto.app.exetion.MainExection;
import auto.app.job.AddXxlJob;
import auto.app.job.UpdateXxlJob;
import auto.app.job.XxlJobTemplate;
import auto.app.model.Scheduled;
import auto.app.dao.ScheduledDao;
import auto.app.model.TestCollection;
import auto.app.service.ScheduledService;
import auto.app.service.TestCollectionService;
import auto.app.util.CommonUtil;
import auto.app.util.ObjectNull;
import auto.app.util.UserGetAccount;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;

import static auto.app.exetion.MainExetionMessage.*;

/**
 * <p>
 * 定时任务配置表 服务实现类
 * </p>
 *
 * @author 杨森
 * @since 2022-09-20
 */
@Service
@Slf4j
public class ScheduledServiceImpl extends ServiceImpl<ScheduledDao, Scheduled> implements ScheduledService {
    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private XxlJobTemplate xxlJobTemplate;

    private static String redisTaskkey = "taskkey:%s";

    @Autowired
    private TestCollectionService testCollectionService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean redisKey(String taskKey, Integer collectId) throws MainExection {
        LambdaQueryWrapper<Scheduled> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Scheduled::getTaskKey, taskKey);
        Scheduled scheduled = baseMapper.selectOne(queryWrapper);
        if (!ObjectUtils.isEmpty(scheduled)) {
            TestCollection byId = testCollectionService.getById(collectId);
            if (ObjectNull.isNull(byId)) {
                throw new MainExection(SELECTCOLLECTERROR.getCode(), SELECTCOLLECTERROR.getMsg());
            }
            redisTemplate.opsForValue().set(String.format(redisTaskkey, scheduled.getTaskKey()), collectId);
            scheduled.setCollectionId(collectId);
            baseMapper.updateById(scheduled);
        } else {
            throw new MainExection(CRONERROR.getCode(), CRONERROR.getMsg());
        }
        return null;
    }

    //分页查询
    @Override
    public ScheduledPageInfo list(ScheduledPage scheduledPage) {
        LambdaQueryWrapper<Scheduled> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.like(ObjectNull.isNotNull(scheduledPage.getTaskKey()), Scheduled::getTaskKey, scheduledPage.getTaskKey())
        .orderByDesc(Scheduled::getCreateTime);
        ScheduledPage scheduledPage1 = baseMapper.selectPage(scheduledPage, lambdaQueryWrapper);
        return CommonUtil.copyOne(scheduledPage1, ScheduledPageInfo.class);
    }

    //新增定时任务
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean addScheduled(ScheduledAdd scheduledAdd) throws MainExection {
        TestCollection byId = testCollectionService.getById(scheduledAdd.getCollectionId());
        if (ObjectNull.isNull(byId)) {
            throw new MainExection(SELECTCOLLECTERROR.getCode(), SELECTCOLLECTERROR.getMsg());
        }
        Scheduled scheduled1 = CommonUtil.copyOne(scheduledAdd, Scheduled.class);
        scheduled1.setCreateTime(LocalDateTime.now());
        scheduled1.setCreateBy(UserGetAccount.getAccountId());
        scheduled1.setCreateName(UserGetAccount.getAccountName());
        //获取执行器
        int jobGroupId = xxlJobTemplate.listGroup().get(0).getId();
        //同步数据到xxl-job
        Integer integer = xxlJobTemplate.addJob(AddXxlJob.builder()
                .jobGroup(jobGroupId)
                .jobDesc(scheduledAdd.getName())
                .author("yangsen")
                .scheduleType("CRON")
                .scheduleConf(scheduledAdd.getCron())
                .executorHandler(JobExecutorHandler.COLLECTIONTEST.getHandler())
                .executorParam(scheduledAdd.getCollectionId().toString()).build());
        scheduled1.setJobId(integer);
        return save(scheduled1);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean start(Integer id) throws MainExection {
        Scheduled scheduled = getById(id);
        if (ObjectNull.isNull(scheduled)) {
            throw new MainExection(CRONADDTASKKEYNOTNULLERROR.getCode(), CRONADDTASKKEYNOTNULLERROR.getMsg());
        }
        if (ObjectNull.isNull(scheduled.getJobId())){
            throw new MainExection(STARTJOBERROR.getCode(), STARTJOBERROR.getMsg());
        }
        if (scheduled.getStatus()==0){
            Boolean start = xxlJobTemplate.start(scheduled.getJobId());
            if (start) {
                scheduled.setStatus(1);
                baseMapper.updateById(scheduled);
                return start;
            }
        }else {
            Boolean start = xxlJobTemplate.stop(scheduled.getJobId());
            if (start) {
                scheduled.setStatus(0);
                baseMapper.updateById(scheduled);
                return start;
            }
        }
        return false;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean delete(Integer id) throws MainExection {
        Scheduled scheduled = getById(id);
        if (ObjectNull.isNull(scheduled)) {
            throw new MainExection(CRONADDTASKKEYNOTNULLERROR.getCode(), CRONADDTASKKEYNOTNULLERROR.getMsg());
        }
        if (ObjectNull.isNull(scheduled.getJobId())){
            return removeById(id);
        }else{
            xxlJobTemplate.removeJob(scheduled.getJobId());
            return removeById(id);
        }

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateScheduled(ScheduledUpdate scheduledUpdate) throws MainExection {
        Scheduled scheduled = getById(scheduledUpdate.getId());
        if (ObjectNull.isNull(scheduled)) {
            throw new MainExection(CRONADDTASKKEYNOTNULLERROR.getCode(), CRONADDTASKKEYNOTNULLERROR.getMsg());
        }
        if (ObjectNull.isNull(scheduled.getJobId())){
            throw new MainExection(STARTJOBERROR.getCode(), STARTJOBERROR.getMsg());
        }
        //获取执行器
        int jobGroupId = xxlJobTemplate.listGroup().get(0).getId();
        //修改定时任务
        xxlJobTemplate.updateJob(UpdateXxlJob.builder()
                .id(scheduled.getJobId())
                .jobGroup(jobGroupId)
                .jobDesc(scheduledUpdate.getName())
                .author("yangsen")
                .scheduleType("CRON")
                .scheduleConf(scheduledUpdate.getCron())
                .executorHandler(JobExecutorHandler.COLLECTIONTEST.getHandler())
                .executorParam(scheduledUpdate.getCollectionId().toString())
                .executorRouteStrategy("FIRST")
                .executorBlockStrategy("SERIAL_EXECUTION")
                .misfireStrategy("DO_NOTHING")
                .build());
        //修改数据信息
        scheduled.setName(scheduledUpdate.getName());
        scheduled.setCron(scheduledUpdate.getCron());
        scheduled.setTaskKey(scheduledUpdate.getTaskKey());
        scheduled.setCollectionId(scheduledUpdate.getCollectionId());
        scheduled.setUpdateBy(UserGetAccount.getAccountId());
        scheduled.setUpdateName(UserGetAccount.getAccountName());
        scheduled.setUpdateTime(LocalDateTime.now());
        return updateById(scheduled);
    }

}
